package com.jcfk.system.service;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jcfk.common.business.enums.AvailableStatus;
import com.jcfk.common.business.enums.DeleteFlag;
import com.jcfk.common.business.service.BaseService;
import com.jcfk.common.cache.redis.service.RedisHashService;
import com.jcfk.common.core.security.JwtUtil;
import com.jcfk.common.core.security.MyPasswordEncoder;
import com.jcfk.common.data.config.MultiTenantConfig;
import com.jcfk.common.security.service.TokenService;
import com.jcfk.common.web.constant.SecurityConstants;
import com.jcfk.common.web.domain.LoginInfo;
import com.jcfk.common.web.domain.LoginParameter;
import com.jcfk.common.web.domain.RetResult;
import com.jcfk.common.web.domain.TokenInfo;
import com.jcfk.common.web.utils.ServletUtils;
import com.jcfk.system.dao.LoginDao;
import com.jcfk.system.dao.SysUserDao;
import com.jcfk.system.domain.dto.PersonLoginRequest;
import com.jcfk.system.domain.dto.PersonalLoginPwdDTO;
import com.jcfk.system.domain.dto.SysUserDTO;
import com.jcfk.system.domain.po.SysUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 登录 业务逻辑
 *
 * @author 李炳海
 */
@Service
public class LoginService extends BaseService<LoginDao, SysUser> {

    @Autowired
    private SysUserDao sysUserDao;

    private static Logger logger = LoggerFactory.getLogger(LoginService.class);

    /**
     * tokenService
     */
    @Autowired
    private TokenService tokenService;

    @Autowired
    private RedisHashService redisHashService;

    @Autowired
    private MultiTenantConfig multiTenantConfig;

    /**
     * 登录
     *
     * @param loginParameter 登录参数
     * @return RetResult
     */
    public RetResult<TokenInfo> login(PersonLoginRequest loginParameter) {
        if (StrUtil.isEmpty(loginParameter.getApplicationType())) {
            loginParameter.setApplicationType("pcWeb");
        }

        TokenInfo tokenInfo = new TokenInfo();
        String loginName = loginParameter.getLoginName();
        String password = loginParameter.getPassWord();
        // 校验登录名和密码
        if (StrUtil.isEmpty(loginName)) {
            return RetResult.fail("登录名不能为空");
        }
        if (StrUtil.isEmpty(password)) {
            return RetResult.fail("密码不能为空");
        }

        // 查询系统用户
        SysUserDTO user = this.getByLoginName(loginParameter.getLoginName());
        if (user == null) {
            return RetResult.fail("登录名或密码不正确");
        }

        if (user.getEnabled().equals(0)) {
            return RetResult.fail("用户已停用");
        }

        // 验证用户名和密码是否正确
        if (!MyPasswordEncoder.getInstance().matches(loginParameter.getPassWord(), user.getPassword())) {
            return RetResult.fail("登录名或密码不正确");
        }

        if (user.getEnabled().equals(AvailableStatus.ENABLE)) {
            return RetResult.fail("用户未启用");
        }

        // 设置登录信息
        LoginInfo loginUser = new LoginInfo();
        loginUser.setUserId(user.getId());
        loginUser.setDepartmentId(user.getDepartmentId());
        loginUser.setOrganizationId(user.getOrganizationId());
        loginUser.setLoginName(user.getLoginName());
        loginUser.setUserName(user.getFirstName());
        loginUser.setLoginTime(new Date());
        loginUser.setApplicationType(loginParameter.getApplicationType());
        loginUser.setUserType(user.getUserType());
        loginUser.getParameters().put("empNo", user.getEmpNo());
        loginUser.getParameters().put("departmentId",user.getDepartmentId());
        loginUser.getParameters().put("departmentName",user.getDepartmentName());

        if (loginParameter.getParameters() != null)
            loginUser.getParameters().putAll(loginParameter.getParameters());
        String token=null;
        if(StrUtil.isEmpty(loginUser.getOrganizationId()))
            token = tokenService.createLogin(loginUser);
        else
            token = tokenService.createLoginTenant(loginUser);
        loginUser.setToken(token);

        // 设置token
        tokenInfo.setStatus(true);
        tokenInfo.setAccessToken(token);

        // 设置用户权限
        Map<String, String> powerCodeMap = new HashMap<>();
        redisHashService.setMap(SecurityConstants.LOGIN_POWER_HEADER + token, powerCodeMap);
        redisHashService.expire("", loginUser.getExpirationMinute(), TimeUnit.MINUTES);

        // 获取客户端IP
        HttpServletRequest request = ServletUtils.getRequest();
        String ip = "127.0.0.1";
        if (request != null) {
            ip = ServletUtils.getClientRequestIp(request);
        }

//        // 记录登陆成功日志
//        logger.info(String.format("登录名：%s,用户名称：%s,通过%s登陆成功，登录ip：%s。",
//                user.getLoginName(),
//                user.getFirstName(),
//                loginParameter.getApplicationType(),
//                ip)
//        );
        return RetResult.ok(tokenInfo);
    }

    /**
     * 通过登录名获取用户信息
     *
     * @param loginName
     * @return
     */
    public SysUserDTO getByLoginName(String loginName) {
        return this.sysUserDao.getByLoginName(loginName);
    }

    /**
     * 生成token
     *
     * @param loginUser 登录信息
     * @return token
     */
    private String createToken(LoginInfo loginUser) {
        String token = "";
        try {
            token = JwtUtil.createToken(loginUser.getUserId(), loginUser.getUserName());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return token;
    }

    /**
     * 获取登录信息
     *
     * @param token
     * @return
     */
    public LoginInfo getLoginInfo(String token) {
        return tokenService.getLoginInfo(token);
    }

    /**
     * 注销登录信息
     *
     * @param token
     */
    public void logout(String token) {
        // 清除登录信息
        tokenService.logout(token);
        // 清除用户权限
        redisHashService.delete(SecurityConstants.LOGIN_POWER_HEADER + token);
    }

    /**
     * 修改个人密码
     *
     * @param loginPwd
     * @return
     */
    public RetResult<?> modifyPassword(PersonalLoginPwdDTO loginPwd) {
        String userId = tokenService.getLoginInfo().getUserId();
        SysUser sysUser = this.baseMapper.selectById(userId);

        // 密码为空校验
        if (StrUtil.isEmpty(loginPwd.getOriginalPassword())) {
            return RetResult.fail("原密码不能为空");
        }
        if (StrUtil.isEmpty(loginPwd.getNewPassword())) {
            return RetResult.fail("新密码不能为空");
        }

        if (!MyPasswordEncoder.getInstance().matches(loginPwd.getOriginalPassword(), sysUser.getPassword())) {
            return RetResult.fail("原密码不正确");
        }

        sysUser.setPassword(MyPasswordEncoder.getInstance().encode(loginPwd.getNewPassword()));

        int count = this.baseMapper.updateById(sysUser);

        return RetResult.ok(count);
    }

}
